package cn.com.utt.unms.service.impl;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.com.utt.common.exception.BusinessException;
import cn.com.utt.common.mapper.UserMapper;
import cn.com.utt.common.service.SmsService;
import cn.com.utt.common.util.Sha256Encode;
import cn.com.utt.common.vo.User;
import cn.com.utt.unms.mapper.AuthSmsMapper;
import cn.com.utt.unms.mapper.DeviceMapper;
import cn.com.utt.unms.mapper.MemberMapper;
import cn.com.utt.unms.mapper.PhoneMacMapper;
import cn.com.utt.unms.mapper.SmslogMapper;
import cn.com.utt.unms.mapper.UserRecordMapper;
import cn.com.utt.unms.mapper.WifiCfgMapper;
import cn.com.utt.unms.mapper.WxCodeMapper;
import cn.com.utt.unms.pojo.Device;
import cn.com.utt.unms.pojo.Member;
import cn.com.utt.unms.pojo.PhoneMac;
import cn.com.utt.unms.pojo.SmsLog;
import cn.com.utt.unms.pojo.UserRecord;
import cn.com.utt.unms.pojo.WifiConf;
import cn.com.utt.unms.pojo.WxCode;
import cn.com.utt.unms.service.JsonService;
import cn.com.utt.unms.vo.AuthResult;

@Service("jsonService")
public class JsonServiceImpl implements JsonService {

	@Autowired
	private DeviceMapper deviceMapper;

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private WifiCfgMapper wifiCfgMapper;

	@Autowired
	private WxCodeMapper wxCodeMapper;

	@Autowired
	private UserRecordMapper userRecordMapper;

	@Autowired
	private MemberMapper memberMapper;

	@Autowired
	private PhoneMacMapper phoneMacMapper;
	
	@Autowired
	private AuthSmsMapper authSmsMapper;
	
	@Autowired
	private SmslogMapper smslogMapper;
	
	@Autowired 
	private SmsService smsService;

	@Override
	@Transactional
	public WxCode checkWxIsRegin(String sn, String mac) {
//		Device device = deviceMapper.queryDeviceBySn(sn);
//
//		User user = userMapper.queryById(device.getUserId());
//
//		return wxCodeMapper.queryByMac(user.getCfgId(), mac);
		return null;
	}

	@Override
	public int onekeyLogin(long cfgId, UserRecord record, String mac) throws BusinessException {
		// 根据user_id查询认证配置信息
		WifiConf wifiConf = wifiCfgMapper.queryWifiConfById(cfgId);
		// 只有微信认证时允许PC使用一键认证
		if (wifiConf != null && (((wifiConf.getAccessType() & 1) == 1)
				|| (((wifiConf.getAccessType() & 4) == 4) && (wifiConf.getWxPcFree() == 1)))) {
			// 认证设置为一键登录
			// 登录
			int state = login(cfgId, record, mac);
			if (state == 0) {
				return 0;
			} else if (state == 3) {
				return 2;
			} else {
				if (state == 1) {
					userRecordMapper.save(record);
				} else {
					userRecordMapper.updateRecordReOnline(record);
				}
				return 1;
				/*
				 * TODO if (state == 1) { return 1; } else { return 0; }
				 */
			}
		} else {
			// 本店没有设置一键登录
			return 0;
		}
	}

	/*
	 * return 0 登录失败 1 登录成功 2登录成功，更新上次登录记录 3登录次数超出限制 4账号并发数超出限制
	 */
	private int login(long cfgId, UserRecord record, String mac) throws BusinessException {
		try {
			// 根据id查询店铺信息
			// 先从memcache中查找
			WifiConf wifiConf = null;
			/*
			 * TODO MemcachedClient client = new MemcachedClient(); String key =
			 * "cfg_" + cfgId; String value = client.get(key);
			 * 
			 * if (value != null && value.length() >= 0) { wifiConf =
			 * JSON.parseObject(value, WifiConf.class); }
			 */
			// 查找不到再去mysql查找
			if (wifiConf == null) {
				wifiConf = wifiCfgMapper.queryWifiConfById(cfgId);
				if (wifiConf != null) {
					// 放入memcache
					/*
					 * TODO value = JSON.toJSONString(wifiConf); client.set(key,
					 * value);
					 */
				}
			}

			// 查找设备信息看设备下面是否是三层环境，三层环境登录限制不生效
			boolean isLayer3 = false;
			Device device = deviceMapper.queryDeviceBySn(record.getSn());
			if (device != null && device.getLayer3() == 1) {
				isLayer3 = true;
			}

			// 是否需要创建新记录
			boolean isNew = true;
			if (wifiConf != null) {
				long timeLimit = 0;
				// 0:手机，1：微信，2：一键, 4:帐号
				switch (record.getAuthType()) {
				case 0:
					timeLimit = wifiConf.getPhoneTmLimit();
					break;
				case 1:
					timeLimit = wifiConf.getWxTmLimit();
					break;
				case 2:
					// 在只开启微信认证情况下，PC一键认证的有效时间按微信认证计算
					if (wifiConf.getAccessType() == 4 && wifiConf.getWxPcFree() == 1) {
						timeLimit = wifiConf.getWxTmLimit();
					} else {
						timeLimit = wifiConf.getFreeTmLimit();
					}
					break;
				case 4:
					// 账号认证的有效时间不能超过账号的有效时间
					timeLimit = wifiConf.getAccountTmLimit();
					break;
				default:
					break;
				}
				LocalDateTime today_start = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);// 当天零点
				String td_st_str = today_start.format(DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss"));
				// 终端的登录次数限制，以mac为标识
				if (wifiConf.getAccessLimit() > 0 && isLayer3 == false) {
					// 有登录限制,通过MAC查今天的登录次数
					int count = userRecordMapper.countTodayLoginByMac(device.getSn(), mac, td_st_str);
					// count与限制正好相等的情况，有可能最后一次还在有效期，所以不能直接禁止
					if (count > wifiConf.getAccessLimit()) {
						// 不能再登录，已超过登录限制
						// 提示
						return 3;
					} else {
						UserRecord userRecord = userRecordMapper.queryTodayLastRecordByMac(device.getSn(), mac,
								td_st_str);
						// 如果当前登录方式与历史登录方式不同，不继续使用上次认证的时间
						if (userRecord != null && userRecord.getAuthType().equals(record.getAuthType())) {
							long cur = System.currentTimeMillis();
							long lefttime = (userRecord.getStartTime().getTime() + timeLimit * 60000) - cur;
							// 上次登录还没有过期，更新上次登录记录状态为在线
							// 需要更新哪些字段？？？？？
							long expire = lefttime / 60000;
							if (expire > 0) {
								if (record.getAuthType() != 4) {
									record.setTimeLimit(expire);
									record.setId(userRecord.getId());
									isNew = false;
								} else {
									// 账号认证，每次都按重新认证处理
									record.setTimeLimit(expire);
								}
							} else {
								// 上次登录的有效期已经过了
								if ((count + 1) > wifiConf.getAccessLimit()) {
									// count正好与access_limit相等，如果上次剩余时间也用完了就超出限制了
									return 3;
								} else {
									// 创建新的记录
									record.setTimeLimit(timeLimit);
								}
							}
						} else {
							// 没有登录记录，创建新的登录记录
							record.setTimeLimit(timeLimit);
						}
					}
				} else {
					// 没有登录限制，创建新的登录记录
					record.setTimeLimit(timeLimit);
				}

				// 账号的并发控制，以username为标识
				// record type==2为微信认证，为什么微信认证不判断并发数限制？？？
				// if (record.getType() != 2 && record.getType() != 1) {
				if (record.getAuthType() != 2) {
					int maxOccurs = wifiConf.getConcurrentLimit();
					if (record.getAuthType() == 4) {
						// 固定账号
						/*
						 * TODO AccountDao accountDao = new AccountDaoImpl();
						 * Account account = accountDao.queryByName(shopId,
						 * record.getUsername()); if (account != null &&
						 * account.getMax_occurs() > 0) { maxOccurs =
						 * account.getMax_occurs(); }
						 */
					}
					// 一建登录没有并发数限制
					if (maxOccurs > 0) {
						List<UserRecord> records = userRecordMapper.queryOnlineByUsername(device.getSn(),
								record.getUsername(), td_st_str);
						if (records != null) {
							for (UserRecord e : records) {
								long lefttime = (record.getStartTime().getTime() + record.getTimeLimit() * 60000)
										- System.currentTimeMillis();
								if (lefttime > 0) {
									records.remove(e);
								}
							}
						}
						int count = 0;
						String firstMac = null;
						long firstID = 0;
						for (UserRecord r : records) {
							// mac地址相同应当不计算并发次数
							if (!r.getMac().equals(record.getMac())) {
								if (firstID == 0) {
									firstID = r.getId();
									firstMac = r.getMac();
								} else if (r.getId() < firstID) {
									firstID = r.getId();
									firstMac = r.getMac();
								}
								count++;
							}
						}
						System.out.println("count:" + count);
						if (count >= maxOccurs) {
							// 该账号的同时登录人数达上限
							// 提示
							// 通过Tr069强制旧的终端下线，允许新的终端上线
							// 查询当前在线的最早记录，并踢下线
							// return 4;
							/*
							 * TODO SetParameterValues setParam = new
							 * SetParameterValues(); setParam.AddValue(
							 * "InternetGatewayDevice.config.webauthglobal.DownUsers",
							 * firstMac); // jmsService.call(dev.getSn(),
							 * setParam); System.out.println("hangup mac:" +
							 * firstMac + ",id:" + firstID + ",shopID:" +
							 * shopId); //RedisRPC.Send(device.getSn(),
							 * setParam);
							 * memberRecordDao.updateRecordStatus(shopId,
							 * firstID, (byte) 2); try { // 更新记录状态为挂断状态
							 * ProtoRPC.Call(device.getSn(), setParam); } catch
							 * (Exception e) { e.printStackTrace(); }
							 */
						}
					}
				}
			} else {
				// 登录失败
				// 直接返回
				return 0;
			}

			// 如果以前登录过，则将以前的记录标记为下线状态
			List<UserRecord> records = null;
			if (isLayer3) {
				records = userRecordMapper.queryOnlineByIP(device.getSn(), record.getIp());
			} else {
				records = userRecordMapper.queryOnlineByMac(device.getSn(), mac);
			}
			if (records != null) {
				long cur = System.currentTimeMillis();
				Timestamp curStamp = new Timestamp(cur);
				for (UserRecord e : records) {
					long lefttime = (e.getStartTime().getTime() + e.getTimeLimit() * 60000) - cur;
					if (lefttime >= 0) {
						// 更新下线时间为当前时间
						userRecordMapper.updateStatusAndEndTimeById(e.getId());
					} else {
						// 更新下线时间为登录时间加上timeLimit
						// Timestamp logoutStamp =
						curStamp = new Timestamp(e.getStartTime().getTime() + e.getTimeLimit() * 60000);
						SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
						userRecordMapper.updateRecordStatus(e.getId(), df.format(curStamp));
					}
				}
			}

			if (isNew) {
				return 1;
			}
			return 2;
		} catch (Exception e) {
			throw new BusinessException(e.getMessage(), e);
		}
	}

	/*
	 * 0：失败，1:成功，2：登录次数超出限制,3：账号并发数超出限制
	 */
	@Override
	public int accountLogin(long userId, UserRecord record, String username, String password, String mac)
			throws BusinessException {

		return 0;
	}

	@Override
	public int wxLogin(long cfgId, UserRecord record, String code, String mac) throws BusinessException {
		// 此时record中的username为null需要从wxCode记录中获取密码
		List<WxCode> wxCodes = wxCodeMapper.queryWxCode(cfgId, code);
		if (wxCodes.size() <= 0) {
			// 密码不正确
			return 0;
		} else {
			// 有密码匹配的，可能是新访客或者已经访问过的访客
			boolean flag = false;
			for (WxCode wxCode : wxCodes) {
				if (wxCode.getExpire().getTime() > System.currentTimeMillis()) {
					// 密码存在，且在有效期
					record.setUsername(wxCode.getOpenid());
					// 如果wxCode状态为0 可用，设置mac为当前mac
					if (wxCode.getStatus() == 0) {
						wxCodeMapper.updateWxCode(cfgId, wxCode.getOpenid(), mac);
						// 将code放回队列，重复使用
						// TODO
						// PasswordFactory.putWxCode2Queue(shopId, code);
					}
					flag = true;
					break;
				}
			}
			if (flag) {
				// 密码正确
				int state = login(cfgId, record, mac);
				if (state == 0) {
					// 登录错误
					return 0;
				} else if (state == 3) {
					return 2;
				} else if (state == 4) {
					return 3;
				} else if (state == 1) {
					// 保存登录记录
					userRecordMapper.save(record);
				} else {
					// 更新登录记录
					userRecordMapper.updateRecordReOnline(record);
				}
				return 1;
			} else {
				// 密码错误
				return 0;
			}
		}
	}

	@Override
	public int phoneLogin(long cfgId, UserRecord record, String phone, String password, String mac)
			throws BusinessException {
		// 登录
		Member member = memberMapper.queryByPhone(phone);
		if (member != null) {
			String upasswd = Sha256Encode.encode(member.getPassword());
			if (password.equals(upasswd)) {
				int state = login(cfgId, record, mac);
				if (state == 0) {
					return 0;
				} else if (state == 3) {
					return 2;
				} else if (state == 4) {
					return 3;
				} else {
					savePhoneRecord(phone, mac);
					if (state == 1) {
						// 保存登录记录
						userRecordMapper.save(record);
					} else {
						// 更新登录记录
						userRecordMapper.updateRecordReOnline(record);
					}
					return 1;
				}
			} else {
				return 0;
			}
		} else {
			return 0;
		}
	}

	private void savePhoneRecord(String phone, String mac) {
		// 手机登录，还需要更新phone_mac表记录
		// 1、查询phone_mac表是否有记录，没有创建
		// 2、有则更新记录
		Member member = memberMapper.queryByPhone(phone);
		if (member != null) {
			// 访问次数增加1，最后访问时间更新
			member.setTotal(member.getTotal() + 1);
			member.setLastTime(new Timestamp(System.currentTimeMillis()));
			memberMapper.updateTotal(member);
		}
		PhoneMac phoneMac = phoneMacMapper.queryRecord(phone, mac);
		if (phoneMac == null) {
			// save
			phoneMac = new PhoneMac();
			phoneMac.setPhone(phone);
			phoneMac.setMac(mac);
			phoneMac.setLoginCount(1L);
			phoneMacMapper.saveRecord(phoneMac);
		} else {
			// update
			phoneMac.setLoginCount(phoneMac.getLoginCount() + 1);
			phoneMacMapper.updateRecord(phoneMac);
		}
	}

	@Override
	public int phoneLogin(long cfgId, UserRecord record, String phone, String mac) throws BusinessException {
		boolean flag = false;
		PhoneMac phoneMac = phoneMacMapper.queryRecord(phone, mac);
		if (phoneMac != null) {
			flag = true;
		} else {
			WifiConf wifiConf = null;
			// 判断是否是免密码登录，则继续处理登录
			/*
			 * TODO MemcachedClient client = new MemcachedClient(); String key =
			 * "cfg_" + shopId; String value = client.get(key); value =
			 * client.get(key); if (value != null && value.length() >= 0) {
			 * wifiConf = JSON.parseObject(value, WifiConf.class); }
			 */
			// 查找不到再去mysql查找
			if (wifiConf == null) {
				wifiConf = wifiCfgMapper.queryWifiConfById(cfgId);
				if (wifiConf != null) {
					// 放入memcache
					/*
					 * TODO value = JSON.toJSONString(wifiConf); client.set(key,
					 * value);
					 */
				}
			}
			if (wifiConf != null && wifiConf.getSimEnable() == 0) {
				flag = true;
			}
		}
		// phone mac有对应记录
		if (flag) {
			// 登录
			int state = login(cfgId, record, mac);
			if (state == 0) {
				//
				return 0;
			} else if (state == 3) {
				return 2;
			} else if (state == 4) {
				return 3;
			} else {
				savePhoneRecord(phone, mac);
				if (state == 1) {
					// 保存登录记录
					userRecordMapper.save(record);
				} else {
					// 更新登录记录
					userRecordMapper.updateRecordReOnline(record);
				}
				if (state == 1) {
					return 1;
				} else {
					return 0;
				}
			}
		} else {

			return 0;
		}
	}

	@Override
	public int checkPhoneIsRegin(String phone, long cfgId, String mac) throws BusinessException {
		
		Member member = memberMapper.queryByPhone(phone);
		boolean needSim = true;
		
		WifiConf wifiConf = null;
		/*
		 * TODO
		 * 先从memcache中查询wifi_cfg
		MemcachedClient client = new MemcachedClient();
		key = "cfg_" + device.getShop_id();
		value = client.get(key);
		if (value != null && value.length() >= 0) {
			wifiConf = JSON.parseObject(value, WifiConf.class);
		}
		*/
		// 查找不到再去mysql查找
		if (wifiConf == null) {
			wifiConf = wifiCfgMapper.queryWifiConfById(cfgId);
			if (wifiConf != null) {
				/*
				 * TODO
				 * 放入memcache
				value = JSON.toJSONString(wifiConf);
				client.set(key, value);
				*/
			}
		}
		if (wifiConf != null && wifiConf.getSimEnable() == 0) {
			needSim = false;
		}
		
		if (member == null) {
			if (!needSim) {
				// 不需要发送短信，注册手机号并返回
				member = new Member();
				Timestamp cur = new Timestamp(System.currentTimeMillis());
				member.setUsername(phone);
				// TODO 从队列获取随机密码
				// String passwd = PasswordFactory.getPhonePassword();
				int code = (int) (Math.random() * 9000 + 1000);
				member.setPassword(String.valueOf(code));
				member.setType((byte) 0);
				member.setFirstTime(cur);
				member.setLastTime(cur);
				// 登录成功以后才会改变total
				member.setTotal(0);
				member.setSmsFailures((byte) 1);
				member.setUpdateTime(cur);

				memberMapper.save(member);

				// 生成phoneMac记录
				// 通过免密码认证的手机，手机号有效性没有得到验证，所以不绑定mac
				/*
				 * PhoneMac phoneMac = new PhoneMac();
				 * phoneMac.setLogin_count(1L); phoneMac.setMac(mac);
				 * phoneMac.setPhone(phone);
				 * phoneMacDao.saveRecord(phoneMac);
				 */
				return 2;
			}
			return 0;
		} else {
			if (!needSim) {
				return 2;
				// 不需要发送短信，注册手机号并返回
				// 已经注册过的手机但没有phoneMac记录，添加phoneMac记录
				/*
				 * PhoneMac phoneMac = phoneMacDao.queryRecord(phone, mac);
				 * if (phoneMac == null) { // 生成phoneMac记录 phoneMac = new
				 * PhoneMac(); phoneMac.setLogin_count(1L);
				 * phoneMac.setMac(mac); phoneMac.setPhone(phone);
				 * phoneMacDao.saveRecord(phoneMac); }
				 */
			}
			PhoneMac phoneMac = phoneMacMapper.queryRecord(phone, mac);
			if (phoneMac != null) {
				return 2;
			}
			return 1;
		}
	}

	@Override
	public int phoneRegin(String phone, long userId,HttpSession session) throws BusinessException {
		// 如果开启了认证短信计数，并且短信数量已用完则直接返回失败
		// 短信余量为－100则表示不计数（例外）
		long num = -1;
		if (true) {
			num = authSmsMapper.countAuthSmsByUserId(userId);
			if (num <= 0 && num != -100) {
				// 短信用完，不能再发送
				return 0;
			}
		}

		// 查询是否已经注册过，防止phone被重复添加
		Member member = memberMapper.queryByPhone(phone);
		if (member == null) {
			// 只有用户不存在时才能注册
			// 获取密码，发送短信
			// TODO
			// String passwd = PasswordFactory.getPhonePassword();
			int passwd = (int) (Math.random() * 9000 + 1000);
			String jsonContent = "{\"code\":\"" + passwd + "\"}";
			int err=smsService.sendSmsResponse(phone, "SMS_149100069",jsonContent, "艾泰科技");
			if (err == 1) {
				//短信发送成功
				session.setAttribute("passwd"+phone, passwd);
				session.setMaxInactiveInterval(31*60);//设置session的过期时间为30分钟，即code有效期为30分钟
			} else {
				// 发送失败
				return 2;
			}
			// 记录短信发送日志
			SmsLog smsLog = new SmsLog();
			smsLog.setMobile(phone);
			smsLog.setUserId(userId);
			smsLog.setType((byte) 0);
			Timestamp stamp = new Timestamp(System.currentTimeMillis());
			smsLog.setStamp(stamp);
			smslogMapper.save(smsLog);
			// 如果开启了认证短信计数，扣除短信数量
			// 短信余量为－100则表示不计数（例外）
			if (true && num > 0) {
				authSmsMapper.subCount(userId);
			}
			member = new Member();
			Timestamp cur = new Timestamp(System.currentTimeMillis());
			member.setUsername(phone);
			// 从队列获取随机密码
			member.setPassword(String.valueOf(passwd));
			member.setType((byte) 0);
			member.setFirstTime(cur);
			member.setLastTime(cur);
			// 登录成功以后才会改变total
			member.setTotal(0);
			member.setSmsFailures((byte) 1);
			member.setUpdateTime(cur);
			// save
			memberMapper.save(member);
		} else {
			return 4;
		}
		// 注册和发送短信都成功
		return 1;
	}

	@Override
	public AuthResult authAvailable(String deviceid, String mac, String token) throws BusinessException {
		// 根据deviceid查询出shop
		try {
			Device device = deviceMapper.queryDeviceBySn(deviceid);
			// 如果设备没有注册
//			if (device.getUserId() == null) {
//				return null;
//			}
			//long cfgId = userMapper.queryById(device.getUserId()).getCfgId();
			long cfgId = 0l;
			UserRecord record = userRecordMapper.queryRecordByToken(token);
			if (record == null) {
				return null;
			} else {
				long expire = 0;
				// 如果cur与login的误差在1分钟以内，就返回time_limit
				long cur = System.currentTimeMillis();
				if ((cur - record.getStartTime().getTime()) > 60000) {
					long lefttime = (record.getStartTime().getTime() + record.getTimeLimit() * 60000)
							- System.currentTimeMillis();
					// 上次登录还没有过期，更新上次登录记录状态为在线
					// 需要更新哪些字段？？？？？
					if (lefttime > 0) {
						expire = lefttime / 60000;
					}
				} else {
					expire = record.getTimeLimit();
				}
				AuthResult result = new AuthResult();
				result.setExpire(expire);
				// 查询店铺速率
				WifiConf wifiConf = null;
				/**
				 * TODO 
				MemcachedClient client = new MemcachedClient();
				String key = "cfg_" + shopId;
				String value = client.get(key);
				if (value != null && value.length() >= 0) {
					wifiConf = JSON.parseObject(value, WifiConf.class);
				}*/
				// 查找不到再去mysql查找
				if (wifiConf == null) {
					wifiConf = wifiCfgMapper.queryWifiConfById(cfgId);
					if (wifiConf != null) {
						// 放入memcache
						/**
						 * TODO
						value = JSON.toJSONString(wifiConf);
						client.set(key, value);*/
					}
				}
				long rate = 0;
				// 0:手机，1：微信，2：一键,4:帐号
				switch (record.getAuthType()) {
				case 0:
					rate = wifiConf.getPhoneRxLimit();
					break;
				case 1:
					rate = wifiConf.getWxRxLimit();
					break;
				case 2:

					if (wifiConf.getAccessType() == 4 && wifiConf.getWxPcFree() == 1) {
						rate = wifiConf.getWxRxLimit();
					} else {
						rate = wifiConf.getFreeRxLimit();
					}
					break;
				case 4:
					rate = wifiConf.getAccountRxLimit();
					break;
				default:
					break;
				}
				// KB/s convert to Kb/s
				result.setRxrate(rate * 8);
				result.setTxrate(0);
				return result;
			}
		} catch (Exception e) {
			throw new BusinessException(e.getMessage(), e);
		}
	}

}